package com.hwtx.form.domain.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hwtx.form.domain.def.OrgTreeOption;
import io.geekidea.boot.common.constant.SystemConstant;
import io.geekidea.boot.framework.exception.BusinessException;
import io.geekidea.boot.system.entity.SysOrg;
import io.geekidea.boot.system.mapper.OrgMapper;
import io.geekidea.boot.system.query.OrgQuery;
import io.geekidea.boot.system.vo.OrgTreeVo;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class OrgService extends ServiceImpl<OrgMapper, SysOrg> {

    @Resource
    OrgMapper orgMapper;

    public List<SysOrg> getOrgs(OrgQuery query) {
        LambdaQueryWrapper<SysOrg> wrapper = new LambdaQueryWrapper<>();
        if (query.getName() != null) {
            wrapper.eq(SysOrg::getName, query.getName());
        }
        List<SysOrg> orgs = orgMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(orgs)) {
            return Lists.newArrayList();
        }
        return orgs;
    }

    public List<OrgTreeVo> getOrgTree(Long parentId, List<SysOrg> orgs) {
        return orgs.stream()
                .filter(vo -> vo.getParentId().equals(parentId))
                .map(org -> {
                    OrgTreeVo treeVo = new OrgTreeVo();
                    treeVo.setId(org.getId());
                    treeVo.setName(org.getName());
                    treeVo.setParentId(org.getParentId());
                    treeVo.setChildren(getOrgTree(org.getId(), orgs));
                    treeVo.setStatus(org.getStatus());
                    treeVo.setSort(org.getSort());
                    treeVo.setType(org.getType());
                    treeVo.setCreateTime(org.getCreateTime());
                    return treeVo;
                }).collect(Collectors.toList());
    }

    public boolean addOrg(SysOrg sysOrg) {
        if (sysOrg.getParentId() != null) {
            SysOrg parent = getById(sysOrg.getParentId());
            if (parent == null) {
                throw new BusinessException("父机构不存在");
            }
        } else {
            sysOrg.setParentId(SystemConstant.ROOT_MENU_ID);
        }
        if (CollectionUtils.isNotEmpty(getByName(sysOrg.getName()))) {
            throw new BusinessException("机构名称已存在");
        }
        return save(sysOrg);
    }

    public boolean updateOrg(SysOrg sysOrg) {
        SysOrg exist = getById(sysOrg.getId());
        if (exist == null) {
            throw new BusinessException("机构不存在Id = " + sysOrg.getId());
        }

        if (getByName(sysOrg.getName()).stream().anyMatch(vo -> !vo.getId().equals(sysOrg.getId()))) {
            throw new BusinessException("机构名称已存在");
        }
        return updateById(sysOrg);
    }

    public boolean deleteOrg(Long orgId) {
        SysOrg sysOrg = getById(orgId);
        if (sysOrg == null) {
            throw new BusinessException("机构不存在Id = " + orgId);
        }
        LambdaQueryWrapper<SysOrg> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysOrg::getParentId, orgId);
        List<SysOrg> children = orgMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(children)) {
            throw new BusinessException("机构下存在子机构，无法删除");
        }
        return removeById(orgId);
    }

    public SysOrg getOrgById(Long orgId) {
        return getById(orgId);
    }

    private List<SysOrg> getByName(String name) {
        LambdaQueryWrapper<SysOrg> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysOrg::getName, name);
        return orgMapper.selectList(wrapper);
    }

    public List<OrgTreeOption> getTreeOption(Long parentId, List<SysOrg> treeData) {
        return treeData.stream()
                .filter(vo -> vo.getParentId().equals(parentId))
                .map(org -> {
                    OrgTreeOption treeVo = new OrgTreeOption();
                    treeVo.setParentId(org.getParentId());
                    treeVo.setChildren(getTreeOption(org.getId(), treeData));
                    treeVo.setValue(org.getId());
                    treeVo.setId(org.getId());
                    treeVo.setLabel(org.getName());
                    treeVo.setName(org.getName());
                    treeVo.setSort(org.getSort());
                    treeVo.setStatus(org.getStatus());
                    if (BooleanUtils.isFalse(org.getStatus())) {
                        treeVo.setIcon("fa fa-check");
                    }
                    return treeVo;
                }).collect(Collectors.toList());
    }
}
